home *** CD-ROM | disk | FTP | other *** search
- Page 60,132
- ;---------------------------------------------------------------
- ; BEGIN LISTING 3
- ;---------------------------------------------------------------
- ;
- ; EMULOAD.ASM Copyright (c) 1991 Robert Collins
- ;
- ; This utility uses '386 LOADALL to emulate '286 LOADALL.
- ; All 16-bit registers are zero-extended to 32-bit
- ; registers. All 24-bit physical addresses are zero-
- ; extended to 32-bit registers. '386-specific registers
- ; not used in '286 LOADALL are either set to the current
- ; values (Debug registers), or zeroed (segment registers).
- ;
- ;---------------------------------------------------------------
- ;
- ; This program assumes that you have run the '386 LOADALL
- ; test prior to installing this TSR. Obviously if LOADALL
- ; has been removed from the '386 mask, then this program
- ; will never work. Likewise, it is easier for me to
- ; document the need to run the LOADALL test program, than
- ; to incorporate it into this code.
- ;
- ;---------------------------------------------------------------
- ;
- ; EMULOAD returns ERROR codes to DOS that can be
- ; intecepted by the batch file command 'IF ERRORLEVEL'.
- ; The following ERRORLEVEL codes are generated by this
- ; program:
- ; 0 = EMULOAD driver now installed in memory
- ; 1 = Attempted removal of the EMULOAD driver from
- ; memory failed because EMULOAD was not in already
- ; in memory.
- ; 2 = The EMULOAD driver was already in memory when an
- ; attempt was made to install it again.
- ; 3 = Bogus command line argument(s).
- ; 4 = Help requested.
- ; 5 = The EMULOAD driver was sucessfully removed from
- ; memory.
- ; 6 = Can't install the EMULOAD driver because this
- ; computer isn't an 80386.
- ;
- ;---------------------------------------------------------------
- ;
- ; Compilation instructions:
- ; MASM EMULOAD; (MASM 5.1)
- ; LINK EMULOAD;
- ; EXE2BIN EMULOAD EMULOAD.COM
- ; DEL EMULOAD.EXE
- ;
- ; The resultant EMULOAD.COM file is 1473 bytes, while the
- ; TSR portion is 1072 bytes.
- ;
- ;---------------------------------------------------------------
- ; Compiler directives
- ;---------------------------------------------------------------
- Title EMULOAD
- .radix 16
- .8086
-
- ;---------------------------------------------------------------
- ; Interrupt vector segment
- ;---------------------------------------------------------------
- ABS0 segment at 0
- org 6*4
- INT_6 dd ?
-
- org 800h
- Loadall_286 dd ?
- ABS0 ends
-
-
- ;---------------------------------------------------------------
- ; Structure definitions
- ;---------------------------------------------------------------
- Desc_cache2 STRUC ; 80286 Descriptor cache
- A15_A00 dw ? ; register layout.
- A23_A16 db ?
- _Type2 db ?
- _Limit2 dw ?
- Desc_cache2 ENDS
-
-
- Desc_cache3 STRUC ; 80386 Descriptor cache
- _Access db 0 ; register layout
- _Type db ?
- _CS32 db 0
- db 0
- _Addr dd ?
- _Limit dd ?
- Desc_cache3 ENDS
-
-
-
- Loadall_struc2 STRUC ; 80286 LOADALL table
- dw 3 dup (?) ; RESERVED
- _286Msw dw ? ; MSW
- dw 7 dup (?) ; RESERVED
- _286Tr dw ? ; TR
- _Flags dw ? ; FLAGS
- _286Ip dw ? ; IP
- _286Ldt dw ? ; LDT
- _286Ds dw ? ; DS
- _286Ss dw ? ; SS
- _286Cs dw ? ; CS
- _286Es dw ? ; ES
- _286Di dw ? ; DI
- _286Si dw ? ; SI
- _286Bp dw ? ; BP
- _286Sp dw ? ; SP
- _286Bx dw ? ; BX
- _286Dx dw ? ; DX
- _286Cx dw ? ; CX
- _286Ax dw ? ; AX
- ES_Desc286 dw 3 dup (?) ; ES Desc. Cache
- CS_Desc286 dw 3 dup (?) ; CS Desc. Cache
- SS_Desc286 dw 3 dup (?) ; SS Desc. Cache
- DS_Desc286 dw 3 dup (?) ; DS Desc. Cache
- Gdt_Desc286 dw 3 dup (?) ; GDTR
- Ldt_Desc286 dw 3 dup (?) ; LDTR
- Idt_Desc286 dw 3 dup (?) ; IDTR
- TSS_Desc286 dw 3 dup (?) ; TSSR
- Loadall_Struc2 ENDS
-
- Loadall_struc3 STRUC
- _Cr0 dd ? ; EAX
- _Eflags dd ? ; EFLAGS
- _Eip dd ? ; EIP
- _Edi dd ? ; EDI
- _Esi dd ? ; ESI
- _Ebp dd ? ; EBP
- _Esp dd ? ; ESP
- _Ebx dd ? ; EBX
- _Edx dd ? ; EDX
- _Ecx dd ? ; ECX
- _Eax dd ? ; EAX
- _Dr6 dd ? ; DR6
- _Dr7 dd ? ; DR7
- _Tr dd ? ; TR
- _Ldt dd ? ; LDT
- _Gs dd ? ; GS
- _Fs dd ? ; FS
- _Ds dd ? ; DS
- _Ss dd ? ; SS
- _Cs dd ? ; CS
- _Es dd ? ; ES
- TSS_Desc dd 3 dup (?) ; TSSR
- IDT_Desc dd 3 dup (?) ; IDTR
- Gdt_Desc dd 3 dup (?) ; GDTR
- Ldt_Desc dd 3 dup (?) ; LDTR
- GS_Desc dd 3 dup (?) ; GS Desc. Cache
- FS_Desc dd 3 dup (?) ; FS Desc. Cache
- DS_Desc dd 3 dup (?) ; DS Desc. Cache
- SS_Desc dd 3 dup (?) ; SS Desc. Cache
- CS_Desc dd 3 dup (?) ; CS Desc. Cache
- ES_Desc dd 3 dup (?) ; ES Desc. Cache
- dd 0ah dup (?) ; RESERVED
- Loadall_Struc3 ENDS
-
- INT_VEC STRUC
- int_offset dw ?
- int_segment dw ?
- INT_VEC ENDS
-
-
- ;---------------------------------------------------------------
- ; Equate definitions
- ;---------------------------------------------------------------
- LOADALL286 equ 050fh
- CRLF equ <0dh,0ah>
- CRLF$ equ <0dh,0ah,'$'>
- INT6 equ [bp-4]
-
-
- ;---------------------------------------------------------------
- ; Macro definitions
- ;---------------------------------------------------------------
- LOADALL_386 MACRO
- db 0fh,07h
- ENDM
-
-
- PRINT_STRING MACRO MSG_NAME
- mov ah,9
- mov dx,offset MSG_NAME
- int 21h
- ENDM
-
-
-
- _TEXT SEGMENT PARA PUBLIC 'CODE'
- Assume CS:_TEXT, DS:_TEXT, ES:_TEXT, SS:_TEXT
- Org 100h
- .386p
- ;---------------------------------------------------------------
- Emulate_286_Loadall Proc Far
- ;---------------------------------------------------------------
- jmp EMULOAD ; goto beginning instruction
-
- Align 4
- ;---------------------------------------------------------------
- ; Local Data
- ;---------------------------------------------------------------
- Loadall_tbl Loadall_Struc3 <>
-
- emuload_msg db "80286 LOADALL EMULATOR utility.",CRLF
- db "Version 1.0 Only for 80386 computers."
- db CRLF
- db "Copyright (c) 1991 Robert Collins."
- db CRLF$
- emu_msg_len equ $-emuload_msg
-
- align 4
- ;---------------------------------------------------------------
- ; TSR Code begins here as an INT06 replacement.
- ;---------------------------------------------------------------
- Int06: push bp
- mov bp,sp
- push si
- push ds
- lds si,[bp][2] ; get CS:IP of bogus
- ; opcode
- cmp word ptr [si],LOADALL286; was it LOADALL?
- jne @Not_LOADALL ; nope
- mov di,0
- mov ds,di
- mov di,cs
- mov es,di
- mov edi,offset Loadall_tbl
-
- Assume DS:ABS0, ES:_TEXT, SS:NOTHING
- ;---------------------------------------------------------------
- ; Convert 80286 registers to 80386 counterparts. The sequencing
- ; order follows the 80386 LOADALL table.
- ;---------------------------------------------------------------
- ; While mapping MSW to CR0, bit5 in CR0 is documented as
- ; RESERVED on the '386 DX, and '1' on the '386 SX. Bit6 is
- ; defined as 'NE' (Numeric Exception) on the '486. If we wanted
- ; this code to work on the '486, then we should mask the lower
- ; nibble of MSW with CR0. But the '486 doesn't have LOADALL,
- ; so this isn't necesary. Next consider the Reserved bit5 on
- ; the '386 DX. Since LOADALL completely redefines the CPU
- ; state, it is safe to clear this reserved bit instead of
- ; masking it with MSW.
- ;---------------------------------------------------------------
- mov eax,cr0 ; MSW --> CR0
- mov ax,Loadall_286._286Msw
- mov Loadall_tbl._CR0,eax
- movzx eax,Loadall_286._Flags ; FLAGS --> EFLAGS
- mov Loadall_tbl._EFLAGS,eax
-
- ;---------------------------------------------------------------
- ; Hereafter MOVZX isn't needed because the upper 16-bits are
- ; guaranteed to be 0.
- ;---------------------------------------------------------------
- mov ax,Loadall_286._286IP ; IP --> EIP
- mov Loadall_tbl._EIP,eax
- mov ax,Loadall_286._286DI ; DI --> EDI
- mov Loadall_tbl._EDI,eax
- mov ax,Loadall_286._286SI ; SI --> ESI
- mov Loadall_tbl._ESI,eax
- mov ax,Loadall_286._286BP ; BP --> EBP
- mov Loadall_tbl._EBP,eax
- mov ax,Loadall_286._286SP ; SP --> ESP
- mov Loadall_tbl._ESP,eax
- mov ax,Loadall_286._286BX ; BX --> EBX
- mov Loadall_tbl._EBX,eax
- mov ax,Loadall_286._286DX ; DX --> EDX
- mov Loadall_tbl._EDX,eax
- mov ax,Loadall_286._286CX ; CX --> ECX
- mov Loadall_tbl._ECX,eax
- mov ax,Loadall_286._286AX ; AX --> EAX
- mov Loadall_tbl._EAX,eax
-
- ;---------------------------------------------------------------
- ; DR6 & DR7 aren't in the '286, so let's use the current values.
- ; By keeping the current values, guarantees that any ICE
- ; breakpoints, or debug register breakpoints are preserved.
- ; (ICE breakpoints use (at least) the upper two of the
- ; 'RESERVED' bits in DR7.
- ;---------------------------------------------------------------
- mov eax,dr6 ; Keep DR6
- mov Loadall_tbl._DR6,eax
- mov eax,dr7 ; Keep DR7
- mov Loadall_tbl._DR7,eax
-
- movzx eax,Loadall_286._286TR ; TR --> TR
- mov Loadall_tbl._TR,eax
- mov ax,Loadall_286._286LDT ; LDT --> LDT
- mov Loadall_tbl._LDT,eax
-
- ;---------------------------------------------------------------
- ; FS & GS aren't in the '286, so let's zero them out.
- ;---------------------------------------------------------------
- xor ax,ax
- mov Loadall_tbl._GS,eax ; Clear GS
- mov Loadall_tbl._FS,eax ; Clear FS
-
- mov ax,Loadall_286._286DS ; DS --> DS
- mov Loadall_tbl._DS,eax
- mov ax,Loadall_286._286SS ; SS --> SS
- mov Loadall_tbl._SS,eax
- mov ax,Loadall_286._286CS ; CS --> CS
- mov Loadall_tbl._CS,eax
- mov ax,Loadall_286._286ES ; ES --> ES
- mov Loadall_tbl._ES,eax
-
- ;-----------------------------------------------------------
- ; Convert '286 descriptor cache register entries to '386
- ; format.
- ;-----------------------------------------------------------
- mov esi,offset Loadall_286.TSS_Desc286
- mov edi,offset Loadall_tbl.TSS_Desc
- call CVT_Desc
- mov esi,offset Loadall_286.IDT_Desc286
- mov edi,offset Loadall_tbl.IDT_Desc
- call CVT_Desc
- mov esi,offset Loadall_286.GDT_Desc286
- mov edi,offset Loadall_tbl.GDT_Desc
- call CVT_Desc
- mov esi,offset Loadall_286.LDT_Desc286
- mov edi,offset Loadall_tbl.LDT_Desc
- call CVT_Desc
-
- ;-----------------------------------------------------------
- ; Fill in FS & GS descriptor cache entires with 0.
- ;-----------------------------------------------------------
- mov Loadall_tbl.GS_Desc._Type,93h
- mov Loadall_tbl.GS_Desc._Addr,0
- mov Loadall_tbl.GS_Desc._Limit,0ffffh
- mov Loadall_tbl.FS_Desc._Type,93h
- mov Loadall_tbl.FS_Desc._Addr,0
- mov Loadall_tbl.FS_Desc._Limit,0ffffh
-
- ;-----------------------------------------------------------
- ; Convert '286 descriptor cache register entries to '386
- ; format.
- ;-----------------------------------------------------------
- mov esi,offset Loadall_286.DS_Desc286
- mov edi,offset Loadall_tbl.DS_Desc
- call CVT_Desc
- mov esi,offset Loadall_286.SS_Desc286
- mov edi,offset Loadall_tbl.SS_Desc
- call CVT_Desc
- mov esi,offset Loadall_286.CS_Desc286
- mov edi,offset Loadall_tbl.CS_Desc
- call CVT_Desc
- mov esi,offset Loadall_286.ES_Desc286
- mov edi,offset Loadall_tbl.ES_Desc
- call CVT_Desc
- mov edi,offset Loadall_tbl
- LOADALL_386
- HLT ; This instruction never
- ; gets executed
-
- @Not_LOADALL:
- pop ds
- pop si
- pop bp
-
- Orig_int06:
- jmp far ptr INT_6
- Emulate_286_Loadall endp
-
-
- ;---------------------------------------------------------------
- CVT_Desc proc near ; Convert '286 descriptor table
- ; ; cache register format to '386
- ; ; format.
- ;---------------------------------------------------------------
- ; Input: DS:ESI = Pointer to '286 descriptor cache entry
- ; DS:EDI = Pointer to '386 descriptor cache entry
- ; Output: None
- ; Register(s) modified: EAX, EBX, ECX
- ;---------------------------------------------------------------
- mov eax,[esi] ; get 24-bit base &
- ; access rights
- mov ebx,eax ; make a copy
- movzx ecx,[esi]._Limit2 ; get 16-bit limit
- rol eax,8 ; put access in AL
- and ebx,00ffffffh ; make 24-bit address
- mov ES:[edi]._Type,al ; store Access
- mov ES:[edi]._Addr,ebx ; store Address
- mov ES:[edi]._Limit,ecx ; store Limit
- ret
- CVT_Desc endp
-
- TSR_End label word
- ;---------------------------------------------------------------
- ; End of TSR program
- ;---------------------------------------------------------------
-
-
- ;---------------------------------------------------------------
- ; Local DATA used for initialization code only.
- ;---------------------------------------------------------------
- bogus_msg1 db "Unrecognized command line argument."
- db CRLF$
- bogus_msg2 db "Not 80386 computer.",7,CRLF$
-
- driver_msg1 db "Resident driver installed."
- db CRLF$
- driver_msg2 db "Resident driver already installed."
- db 7,CRLF$
- driver_msg3 db "Resident driver removed from memory."
- db CRLF$
- driver_msg4 db "Resident driver was not already "
- db "installed",7,CRLF$
- help_msg db CRLF
- db "Syntax: EMULOAD",CRLF
- db " EMULOAD -R (to remove from "
- db "memory)",CRLF$
-
-
- ASSUME DS:_TEXT
- ;---------------------------------------------------------------
- EMULOAD proc near ; Beginning of initialization
- ; ; code as the NON-TSR part of
- ; ; the program.
- ;---------------------------------------------------------------
- cld ; clear direction flag
- Print_String emuload_msg ; Print initialization
- ; message.
-
- ;---------------------------------------------------------------
- ; Check CPU type
- ;---------------------------------------------------------------
- call CPU_TYPE ; Get CPU type
- and al,0fh ; mask out CPU sub-type
- cmp al,3 ; 80386?
- jz short @F ; yes
- Print_String Bogus_msg2 ; Not 80386 computer
- mov ax,4c06h ; set function to DOS
- int 21h ; exit to DOS
-
- ;---------------------------------------------------------------
- ; Check command line argument
- ;---------------------------------------------------------------
- @@: xor ax,ax ; clear AX
- mov si,80h ; get start of PSP
- lodsb ; get command line len.
- or ax,ax ; Any command line args?
- jz short Installed? ; nope
- mov cx,ax ; put into counter
- mov di,si ;
- mov al,' ' ; skip past superfluous
- repz scasb ; blank characters
- cmp byte ptr [di],0dh ; are we at the end?
- jz short Installed? ; yep
- cmp byte ptr [di-1],'-' ; check if it's a switch
- jnz short @F ; if not, then error
- mov si,di ; get pointer
- lodsb ; get cmd line switch
- cmp al,'r' ; remove driver?
- jz short remove_driver ; yep
- cmp al,'R' ; remove driver?
- jz short remove_driver ; go remove driver
- cmp al,'?' ; help?
- jnz short @F ; nope
- Print_String help_msg ; Print help message
- mov ax,4c04h ; set return code
- int 21h ; exit to DOS
-
- ;---------------------------------------------------------------
- ; Bogus command line argument
- ;---------------------------------------------------------------
- @@: Print_String bogus_msg1 ; Invalid command line
- mov ax,4c03h ; set function code
- int 21h ; exit to DOS
-
- ;---------------------------------------------------------------
- ; Remove driver from memory
- ;---------------------------------------------------------------
- remove_driver:
- call check_installed ; Driver installed?
- jnz short @F ; driver not installed
- mov bp,sp ; create stack frame
- push ds ; save (DS)
- mov dx,ABS0 ; get bottom of memory
- mov ds,dx ; make segment register
-
- ASSUME DS:ABS0, ES:_TEXT
- ;---------------------------------------------------------------
- ; Restore original INT6 vector
- ;---------------------------------------------------------------
- ; We can restore the original INT6 by getting the vector from
- ; our current memory resident driver -- not the DS from the
- ; code now executing. The original DS is the same as the code
- ; segment for our EMULOAD driver. Hence we only need to get
- ; the original segment value from the memory resident image.
- ; And we get this by looking at the segment for INT6!
- ;---------------------------------------------------------------
- mov es,int_6.int_segment ; Original DS
- mov ax,es:orig_int06[1].int_offset ; Original INT6
- mov bx,es:orig_int06[1].int_segment ; " "
- mov int_6.int_offset,ax ; Restore orig.
- mov int_6.int_segment,bx ; INT6
-
- ;---------------------------------------------------------------
- ; Free memory pointed to by ES
- ;---------------------------------------------------------------
- mov ah,49h ; DOS FREE_MEM function
- int 21h ; free allocated memory
- mov ds,[bp-2] ; get original (DS)
-
- ASSUME DS:_TEXT
- ;---------------------------------------------------------------
- ; Now split with TSR removed from memory.
- ;---------------------------------------------------------------
- Print_String driver_msg3 ; Driver removed
- mov ax,4c05h ; set function to DOS
- int 21h ; exit to DOS
-
- ;---------------------------------------------------------------
- ; If EMULOAD was not in memory, then come here and split with
- ; the error code.
- ;---------------------------------------------------------------
- @@: Print_String driver_msg4 ; Driver not installed
- mov ax,4c01h ; set function to DOS
- int 21h ; exit to DOS
-
- ;---------------------------------------------------------------
- ; Check for driver already installed
- ;---------------------------------------------------------------
- Installed?:
- call check_installed ; check if driver is
- jnz short @F ; already installed?
-
- ;---------------------------------------------------------------
- ; Driver already installed
- ;---------------------------------------------------------------
- Print_String driver_msg2 ; Driver already inst.
- mov ax,4c02h ; set function to DOS
- int 21h ; exit to DOS
-
- ;---------------------------------------------------------------
- ; Driver not yet installed
- ;---------------------------------------------------------------
- @@: Print_String driver_msg1 ; Driver now installed
-
- ;---------------------------------------------------------------
- ; Install driver into memory
- ;---------------------------------------------------------------
- xor dx,dx ; Point to INT. vectors
- mov ds,dx ; complete the move
- ASSUME ds:ABS0
-
- ;---------------------------------------------------------------
- ; Chain to INT6 by replacing and saving the original INT6
- ; vector.
- ;---------------------------------------------------------------
- mov ax,int_6.int_offset ; Orig. offset
- mov bx,int_6.int_segment ; Orig. segment
- mov orig_int06[1].int_offset,ax ; save old INT6
- mov orig_int06[1].int_segment,bx ; vector.
-
- ;---------------------------------------------------------------
- ; Now replace the original INT6 vector.
- ;---------------------------------------------------------------
- mov dx,offset cs:int06 ; Get new INT6 vector
- mov int_6.int_offset,dx ; as CS:INT6
- mov int_6.int_segment,cs ;
-
- ASSUME DS:_TEXT
- ;---------------------------------------------------------------
- ; Terminate and Stay Resident
- ;---------------------------------------------------------------
- mov dx,cs ; make DS=CS
- mov ds,dx
- mov es,ds:[2ch] ; get DOS env. segment
- mov ah,49h ; release memory func.
- int 21h ; release memory
- mov dx,offset tsr_end ; get ending address
- shr dx,4 ; divide by 16
- adc dx,1 ; check for remainder;
- ; add 1
- mov ax,3100h ; set return code to DOS
- int 21h
- EMULOAD endp
-
-
- ASSUME ES:ABS0
- ;---------------------------------------------------------------
- ; Check to see if the EMULOAD driver is installed in memory.
- ; It is possible to check if a TSR program is already installed
- ; in memory by looking for a semaphore in the memory image.
- ; Luckily we can locate the memory image of our TSR by looking
- ; at the current INT6 vector. The INT6 code segment is the
- ; segment of the TSR! So this routine looks in this segment
- ; for the inital banner message:
- ;
- ; 80286 LOADALL EMULATOR utility.
- ; Version 1.0 Only for 80386 computers.
- ; Copyright (c) 1991 Robert Collins.
- ;
- ; If this message is found, then the TSR is in memory. If
- ; another TSR has chained to the same INT6 vector, this
- ; technique will fail to find EMULOAD, as it very well should!
- ;---------------------------------------------------------------
- Check_installed proc near
- ;---------------------------------------------------------------
- ; Input: None
- ; Output: NZ if NOT installed
- ; ZF if ALREADY installed
- ; Register(s) modified: CX, SI, DI
- ;---------------------------------------------------------------
- push es ; save (ES)
- mov cx,ABS0 ; get bios data segment
- mov es,cx ; put in (ES)
- mov cx,emu_msg_len ; # of bytes to compare
- mov si,offset emuload_msg ; get address of message
- les di,ES:INT_6 ; get INT6 vector
- sub di,int06-emuload_msg ; point to theoretical
- ; start of message
- repz cmpsb ; check data
- pop es ; restore (ES)
- ret ; split
- Check_installed endp
-
-
- ;---------------------------------------------------------------
- ; Include the CPU_TYPE procedure & LOADALL test
- ;---------------------------------------------------------------
- Include CPU_TYPE.ASM
-
- _TEXT ends
- end Emulate_286_LOADALL
-
- ;---------------------------------------------------------------
- ; END LISTING 3
- ;---------------------------------------------------------------
-